#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

#include <linux/jiffies.h>
#include <linux/ktime.h>

#include "log.h"
#include "current_time.h"
#include "busy.h"
#include "schedule.h"
#include "queue.h"
#include "timer.h"
#include "tasklet.h"
#include "workqueue.h"

module_param(busy_interval, uint, 0644);
module_param(sched_interval, uint, 0644);
module_param(queue_interval, uint, 0644);
module_param(timer_interval, uint, 0644);

/**
 * Whether tasklets should be scheduled with high priority.
 * 0: normal priority (default)
 * 1: high priority
 */
module_param(tasklet_high_priority, uint, 0644);
/**
 * Whether create module owned workqueue.
 * 0: use system workqueue (default)
 * 1: create module owned workqueue
 */
module_param(owned_workqueue, uint, 0644);
module_param(workqueue_delay, uint, 0644);

static int __init jit_module_init(void) {
    LOGI("enter");
    int ret = 0;
    // create proc file
    proc_create("jitcurrenttime", 0644, NULL, &current_time_ops);
    proc_create("jitbusy", 0644, NULL, &busy_ops);
    proc_create("jitsched", 0644, NULL, &sched_ops);
    proc_create("jitqueue", 0644, NULL, &queue_ops);
    ret = jit_timer_init();
    if (ret) {
        LOGE("jit_timer_init failed: %d", ret);
        return ret;
    }
    ret = jit_tasklet_init();
    if (ret) {
        LOGE("jit_tasklet_init failed: %d", ret);
        jit_timer_exit();
        return ret;
    }
    ret = jit_workqueue_init();
    return ret;
}
module_init(jit_module_init);

static void __exit jit_module_exit(void) {
    // read_method:
    // cat /proc/jiqwq
    jit_workqueue_exit();
    // read_method:
    // cat /proc/jitasklet
    jit_tasklet_exit();
    // read_method:
    // cat /proc/jittimer or cat /dev/jittimer
    jit_timer_exit();
    // read method:
    // dd bs=25 count=5 status=none < /proc/jitqueue
    remove_proc_entry("jitqueue", NULL);
    // read method:
    // dd bs=25 count=5 status=none < /proc/jitsched
    remove_proc_entry("jitsched", NULL);
    // read method:
    // dd bs=25 count=5 status=none < /proc/jitbusy
    remove_proc_entry("jitbusy", NULL);
    // read method:
    // head -n 8 /proc/jitcurrenttime
    remove_proc_entry("jitcurrenttime", NULL);
}
module_exit(jit_module_exit);

MODULE_LICENSE("GPL");